// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// h [author] rhyme_lph
// h [email]  rhymelph@gmail.com
// V [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/employee_dot_entity.dart';
import 'package:finance_app/src/entities/expense_detail_entity.dart';
import 'package:finance_app/src/entities/leave_item_entity.dart';
import 'package:finance_app/src/http_service/http_employee_contact_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/provider/dashboard_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/employee_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/leave_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/payroll_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/reimburse_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/permission_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/dashboard_add_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class HrAndPayrollProvider extends BaseProvider with CheckPlanMixin {
  List<String> menuList = [
    'Add',
    'Mark As Resigned',
  ];

  List<String> tabs = [
    S.current.employee,
    S.current.payroll,
    S.current.reimburse,
    S.current.leave,
  ];

  List<String> hasBadgeList = [];

  int currentIndex = 0;
  TabController tabController;

  bool get addIsShow {
    if (!Config.hasPermission(PermissionUtils.hrPayroll)) {
      return currentIndex != 0 && currentIndex != 1;
    } else {
      return true;
    }
  }

  bool buttonBarIsUp = true;

  void handleScrollUpdate(ScrollController controller) {
    if (controller.position.userScrollDirection == ScrollDirection.reverse &&
        buttonBarIsUp == true) {
      //向下滑动
      buttonBarIsUp = false;
      update();
    }
    if (controller.position.userScrollDirection == ScrollDirection.forward &&
        buttonBarIsUp == false) {
      buttonBarIsUp = true;
      update();
    }
  }

  @override
  Future get dataFuture => null;

  @override
  void initState() {
    super.initState();
    if (Config.isStaff) {
      menuList = [];
    } else {
      menuList = [
        'Add',
        'Mark As Resigned',
      ];
    }
    loadEmployeeDots();
  }

  void onSelectMenu(String value) async {
    if (isPlanExpired()) return;
    switch (value) {
      case "Import":
        Routes.navigateTo(RouterGenProviders.hrAndPayrollDataImportPage);
        break;
      case 'Mark As Resigned':
        await Routes.navigateTo(RouterGenProviders.markAsResignedPage);
        getChildProvider<EmployeeProvider>().loadData();
        break;
      case 'Add':
        await Routes.navigateTo(RouterGenProviders.newEmployeePage);
        getChildProvider<EmployeeProvider>().loadData();
        break;
      case 'Duplicate As New':
        await Routes.navigateTo(RouterGenProviders.duplicateAsNewPage);
        break;
      case 'Delete':
        if (currentIndex == 3) {
          await Routes.navigateTo(RouterGenProviders.leaveOperationPage,
              params: {
                'operation': 'Delete',
              });
          getChildProvider<LeaveProvider>().refreshDashboard();
        } else if (currentIndex == 2) {
          await Routes.navigateTo(RouterGenProviders.reimburseApprovePage,
              params: {
                'operation': 'Delete',
              });
        } else {
          await Routes.navigateTo(RouterGenProviders.payrollDeletePage);
        }
        break;
      case 'Generate Payslip':
        await Routes.navigateTo(RouterGenProviders.employeeBatchSelectPage,
            params: {"pageTitle": S.current.generate_payslip});
        break;
      case 'Record Payment':
        await Routes.navigateTo(RouterGenProviders.payrollPaymentPage);
        break;
      case 'Record CPF Contribution':
        await Routes.navigateTo(
          RouterGenProviders.recordCpfContributionPage,
        );
        break;
      case 'Apply Leave':
        await Routes.navigateTo(RouterGenProviders.newLeavePage);
        getChildProvider<LeaveProvider>().refreshDashboard();
        break;
      case 'Approve':
        await Routes.navigateTo(RouterGenProviders.leaveOperationPage, params: {
          'operation': 'Approve',
        });
        getChildProvider<LeaveProvider>().refreshDashboard();
        break;
      case 'Reimburse Now':
        await Routes.navigateTo(RouterGenProviders.reimburseApprovePage,
            params: {
              'operation': 'Reimburse Now',
            });
        getChildProvider<ReimburseProvider>().loadDashboard();
        break;
      case 'Reimburse Later':
        await Routes.navigateTo(RouterGenProviders.reimburseApprovePage,
            params: {
              'operation': 'Reimburse Later',
            });
        getChildProvider<ReimburseProvider>().loadDashboard();
        break;
      case 'Reject':
        if (currentIndex == 2) {
          await Routes.navigateTo(RouterGenProviders.reimburseApprovePage,
              params: {
                'operation': 'Reject',
              });
          getChildProvider<ReimburseProvider>().loadDashboard();
        } else {
          await Routes.navigateTo(RouterGenProviders.leaveOperationPage,
              params: {
                'operation': 'Reject',
              });
          getChildProvider<LeaveProvider>().refreshDashboard();
        }
        break;
      case 'Withdraw':
        await Routes.navigateTo(RouterGenProviders.leaveOperationPage, params: {
          'operation': 'Withdraw',
        });
        getChildProvider<LeaveProvider>().refreshDashboard();
        break;
      case 'Leave Adjustment':
        await Routes.navigateTo(RouterGenProviders.leaveAdjustmentPage);
        getChildProvider<LeaveProvider>().refreshDashboard();
        break;
      case 'Add Expense Claim':
        onNavAdd();
        break;
    }
  }

  @override
  List<BaseProvider> registerChildProviders() {
    return [
      EmployeeProvider(),
      PayrollProvider(),
      ReimburseProvider(),
      LeaveProvider(),
    ];
  }

  void onNavAdd() async {
    if (isPlanExpired()) return;
    if (tabController != null) {
      currentIndex =
          (tabController.index + tabController.offset).round().clamp(0, 100);
    }
    obtainContext?.call((context) {
      FocusScope.of(context).requestFocus(FocusNode());
    });
    if (currentIndex == 0) {
      Routes.navigateTo(RouterGenProviders.newEmployeePage);
    } else if (currentIndex == 1) {
      obtainContext?.call((context) async {
        await showDashboardAddBottomSheet(context,
            dashTypes: [DashBoardAddType.payroll]);
        getChildProvider<PayrollProvider>().onRefresh();
      });
      // Routes.navigateTo(RouterGenProviders.employeeBatchSelectPage,
      //     params: {"pageTitle": "Generate Payslip"});
    } else if (currentIndex == 2) {
      final result =
          await Routes.navigateTo(RouterGenProviders.newExpensePage, params: {
        'isSelectMode': true,
        'isHidePaid': true,
      });
      if (result != null && result is ExpenseDetailEntity) {
        getChildProvider<ReimburseProvider>()
            ?.refreshController
            ?.requestRefresh();
      }
    } else if (currentIndex == 3) {
      final result = await Routes.navigateTo(RouterGenProviders.newLeavePage);
      if (result != null) {
        getChildProvider<LeaveProvider>().addItem(result as LeaveItemEntity);
      }
    }
  }

  void onSelectMenuChange(int page, [bool shouldUpdate = true]) {
    List<String> dataList = [];
    if (page == 0) {
      if (Config.isStaff) {
        dataList = [];
      } else {
        dataList = getChildProvider<EmployeeProvider>()?.menuList ??
            [
              'Add',
              'Mark As Resigned',
            ];
      }
    } else if (page == 1) {
      if (Config.isStaff) {
        dataList = [];
      } else {
        dataList = [
          'Delete',
          'Generate Payslip',
          'Record Payment',
          'Record CPF Contribution',
        ];
      }
    } else if (page == 2) {
      if (Config.isStaff) {
        dataList = [
          'Add Expense Claim',
          'Delete',
        ];
      } else {
        dataList = [
          'Add Expense Claim',
          'Reimburse Now',
          'Reimburse Later',
          'Reject',
          'Delete',
        ];
      }
    } else if (page == 3) {
      if (Config.isStaff) {
        dataList = [
          'Apply Leave',
          'Delete',
        ];
      } else {
        dataList = [
          'Apply Leave',
          'Approve',
          'Reject',
          'Delete',
          'Withdraw',
          'Leave Adjustment'
        ];
      }
    }
    if (menuList != dataList) {
      menuList = dataList;
      if (shouldUpdate == true) {
        update();
        getParentProvider<DashboardProvider>()?.update();
      }
    }
  }

  void onChangeTab(TabController tabController) {
    int page = (tabController.index + tabController.offset).round();

    currentIndex = page;
    if (!tabController.indexIsChanging) {
      if (currentIndex == 0) {
        getChildProvider<EmployeeProvider>().loadData();
      }
    }
    onSelectMenuChange(page);
  }

  Future<void> loadEmployeeDots() async {
    hasBadgeList.clear();
    await post(HttpEmployeeContactService.showDots(),
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      EmployeeDotEntity dots = getEntityFromResult<EmployeeDotEntity>(result);
      if (dots.payroll > 0) {
        hasBadgeList.add('Payroll');
      }
      if (dots.leave > 0) {
        hasBadgeList.add('Leave');
      }
      if (dots.reimburse > 0) {
        hasBadgeList.add('Reimburse');
      }
      update();
    });
  }
}
